﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/10/24 9:35:26
* 描述：
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using CommonLibrary;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.Threading;

namespace SCADA
{
    /// <summary>
    /// 出站
    /// </summary>
    public class CleanManager
    {
        /// <summary>
        /// 出站配置
        /// </summary>
        public static MultiPLCStationTag PLC_STATION_TAGS = MultiPLCStationTag.Load();
        /// <summary>
        /// 定义接口
        /// </summary>
        private static readonly Lazy<CleanManager> _instance = new Lazy<CleanManager>(() => new CleanManager());
        /// <summary>
        /// 类入口
        /// </summary>
        public static CleanManager Instance
        {
            get
            {
                return _instance.Value;
            }
        }
        #region 线程定义
        /// <summary>
        /// 出站线程
        /// </summary>
        List<Thread> ThreadList = new List<Thread>();
        #endregion
        /// <summary>
        /// 初始化
        /// </summary>
        public void Init()
        {
        }
        private static List<PLCTagSetting> TRIGGER_ADDRESS_TAGS = new List<PLCTagSetting>();
        private static object LOCK_TRIGGER_ADDRESS_DIC = new object();
        private static Dictionary<string, short> TRIGGER_VALUES = new Dictionary<string, short>();

        private static void InitTriggers(List<string> triggers)
        {
            if (triggers != null && triggers.Count > 0)
            {
                TRIGGER_ADDRESS_TAGS.Clear();
                foreach (var s in triggers)
                {
                    TRIGGER_ADDRESS_TAGS.Add(new PLCTagSetting()
                    {
                        ORMName = s,
                        Tag = s,
                        TypeName = "short"
                    });
                }
            }
            lock (LOCK_TRIGGER_ADDRESS_DIC)
            {
                TRIGGER_VALUES.Clear();
                foreach (var s in triggers)
                {
                    TRIGGER_VALUES.Add(s, 0);
                }
            }
            lock (LOCK_DISABLE) {
                DISABLE_TRIGGERS.Clear();
            }
        }
        private static short GetTriggerValue(string address)
        {
            lock (LOCK_TRIGGER_ADDRESS_DIC)
            {
                return TRIGGER_VALUES != null && TRIGGER_VALUES.Count > 0 && TRIGGER_VALUES.ContainsKey(address) ? TRIGGER_VALUES[address] : (short)0;
            }
        }
        private static List<string> DISABLE_TRIGGERS = new List<string>();
        private static object LOCK_DISABLE = new object();
        private static bool IsDisable(string triggerAddress)
        {
            lock (LOCK_DISABLE)
            {
                return string.IsNullOrWhiteSpace(triggerAddress) ? false : DISABLE_TRIGGERS.Contains(triggerAddress);
            }
        }
        private static void SetDisable(string triggerAddress)
        {
            lock (LOCK_DISABLE)
            {
                if (!string.IsNullOrWhiteSpace(triggerAddress) && !DISABLE_TRIGGERS.Contains(triggerAddress))
                {
                    DISABLE_TRIGGERS.Add(triggerAddress);
                }
            }
        }
        private static void ClearDisable(string triggerAddress)
        {
            lock (LOCK_DISABLE)
            {
                if (!string.IsNullOrWhiteSpace(triggerAddress) && DISABLE_TRIGGERS.Contains(triggerAddress))
                {
                    DISABLE_TRIGGERS.Remove(triggerAddress);
                }
            }
        }
        /// <summary>
        /// 启动
        /// </summary>
        public void StartThread()
        {
            StopThread();
            ThreadList.Clear();
            PLC_STATION_TAGS = MultiPLCStationTag.Load();
            if (PLC_STATION_TAGS != null
                && PLC_STATION_TAGS.MultiStationTagList != null
                && PLC_STATION_TAGS.MultiStationTagList.Count > 0)
            {
                #region 收集触发地址
                List<string> triggers = new List<string>();
                foreach (var p in PLC_STATION_TAGS.MultiStationTagList)
                {
                    if (!string.IsNullOrWhiteSpace(p.TriggerAddress))
                    {
                        triggers.Add(p.TriggerAddress);
                    }
                }
                InitTriggers(triggers);
                new Thread(() =>
                {
                    while (GlobalStatus.APP == EAppStatus.RUN)
                    {
                        if (APPInstance.IsPLCConnected)
                        {
                            var values = APPInstance.PLC.BatchRead(TRIGGER_ADDRESS_TAGS);
                            lock (LOCK_TRIGGER_ADDRESS_DIC)
                            {
                                foreach (var key in values.Keys)
                                {
                                    if (!IsDisable(key))
                                    {
                                        try
                                        {
                                            TRIGGER_VALUES[key] = (short)values[key];
                                        }
                                        catch (Exception ex)
                                        {
                                            LogHelper.Error(ex);
                                        }
                                    }
                                    else
                                    {
                                        TRIGGER_VALUES[key] = 0;
                                    }
                                }
                            }
                        }
                        Thread.Sleep(50);
                    }
                })
                { IsBackground = true }.Start();
                #endregion

                for (var i = 0; i < PLC_STATION_TAGS.MultiStationTagList.Count; i++)
                {
                    var tag = PLC_STATION_TAGS.MultiStationTagList[i];
                    Thread t = new Thread(() =>
                    {
                        ReadPLCStation(tag);
                    });
                    t.IsBackground = true;
                    ThreadList.Add(t);
                }
                foreach (var thread in ThreadList)
                {
                    if (thread != null)
                    {
                        thread.Start();
                    }
                }
            }
        }
        /// <summary>
        /// 停止
        /// </summary>
        public void StopThread()
        {
        }
        /// <summary>
        /// 采集出站数据
        /// </summary>
        /// <param name="tag">PLC地址配置内容</param>
        public void ReadPLCStation(MultiPLCTagParameter tag)
        {
            FormMain.Instance.AddRunningViewLog(Color.White, $"开启监控工位 {tag.Remark} 出站采集线程");
            while (GlobalStatus.APP == EAppStatus.RUN)
            {
#if DEBUG
                LogHelper.Debug($"【采集出站数据】 {tag.Remark} 开始：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
#endif
                #region 读取数据工位
                short iOutbound = GetTriggerValue(tag.TriggerAddress);//APPInstance.PLC.ReadShort(tag.TriggerAddress);

                if ((short)1 == iOutbound)
                {
                    SetDisable(tag.TriggerAddress);
#if DEBUG
                    LogHelper.Debug($"【采集出站数据】 {tag.Remark} 读到触发值：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
#endif
                    try
                    {
                        var isOk = tag.Remark.ToUpper().StartsWith("OK");
                        FormMain.Instance.AddRunningViewLog(isOk ? Color.White : Color.Red, $"{tag.Remark} 触发出站采集");
                        Stopwatch watch = Stopwatch.StartNew();
                        if (tag != null && tag.Parameters != null && tag.Parameters.Count > 0)
                        {
                            int itemIndex = 0;
                            foreach (var param in tag.Parameters)
                            {
                                var entity = new OutboundExcuteEntity()
                                {
                                    Index = itemIndex,
                                    OutType = tag.OutType,
                                    PLCTags = param,
                                    Remark = tag.Remark,
                                    ResultAddress = tag.ResultAddress,
                                };
                                PluginManager.Instance.Excute(PluginParam.Instance().GetPluginParam($"{tag.Remark}出站", "OUTBOUND_DATA", CommonHelper.GetJsonString(entity, Formatting.None)));
                                itemIndex++;
                            }
                        }
                        watch.Stop();
                        PluginManager.Instance.Excute(PluginParam.Instance().GetPluginParam($"{tag.Remark}出站", "OUTBOUND_FINISH", CommonHelper.GetJsonString(
                            new OutboundFinishExcuteEntity()
                            {
                                DoneAddress = tag.DoneAddress,
                                TriggerAddress = tag.TriggerAddress,
                            }, Formatting.None)));

                        FormMain.Instance.AddRunningViewLog(isOk ? Color.White : Color.Red, $"{tag.Remark} 采集完毕，耗时: {watch.ElapsedMilliseconds} 毫秒。");
                    }
                    catch (Exception ex)
                    {
                        LogHelper.Error(ex);
                    }

                    ClearDisable(tag.TriggerAddress);
                }
                #endregion


#if DEBUG
                LogHelper.Debug($"【采集出站数据】 {tag.Remark} 结束：{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}");
#endif
                Thread.Sleep(50);
            }
            FormMain.Instance.AddRunningViewLog(Color.Red, $"{tag.Remark} 出站采集线程已停止");
        }
    }
}
